package com.guodi.map.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guodi.common.utils.PageData;
import com.guodi.common.utils.ReadFileUtil;
import com.guodi.map.constant.MapConst;
import com.guodi.map.entity.MapLayer;
import com.guodi.map.entity.MapLayerField;
import com.guodi.map.mapper.MapFunctionDirMapper;
import com.guodi.map.mapper.MapLayerMapper;
import com.guodi.map.mapper.MapProjectDirMapper;
import com.guodi.map.service.IMapLayerFieldService;
import com.guodi.map.service.IMapLayerService;
import com.guodi.map.service.IMapMetadataService;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @描述：地图图层表 服务类
 * @作者: 代鹏刚
 * @日期: 2019-12-11
 */
@Service
public class MapLayerServiceImpl extends ServiceImpl<MapLayerMapper, MapLayer> implements IMapLayerService {

    @Resource
    private MapLayerMapper mapLayerMapper;
    @Resource
    private IMapLayerFieldService mapLayerFieldService;
    @Resource
    private IMapLayerService mapLayerService;
    @Resource
    private IMapMetadataService mapMetadataService;
    @Resource
    private MapProjectDirMapper projectDirMapper;
    @Resource
    private MapFunctionDirMapper functionDirMapper;

    @Override
    public List<MapLayer> listByEntity(PageData pd){
        return mapLayerMapper.listByEntity(pd);
    }

    @Override
    public List<MapLayer> listLazyByEntity(PageData pd) {
        return mapLayerMapper.listLazyByEntity(pd);
    }

    @Override
    @Cacheable(cacheNames = "layer", key = "#id")
    public String getLayerUrlById(String id) {
        MapLayer byId = this.getById(id);
        return byId == null ? "" : byId.getLayerUrl();
    }


    @Override
    public void saveMaplayer(MapLayer mapLayer,boolean insertFlag) {
        // 图层id(一定要先取值，否则保存图层后id值会改变)
        String layerId = mapLayer.getId();
        if(insertFlag){
            // 保存图层
            this.baseMapper.insert(mapLayer);
        }else{
            baseMapper.updateById(mapLayer);
        }
        //如果是wmts或者wms或者天地图，直接跳过
        if(StringUtils.isNotBlank(mapLayer.getLayerType()) && (MapConst.WMTS.equals(mapLayer.getLayerType().toLowerCase()) || MapConst.WMS.equals(mapLayer.getLayerType().toLowerCase()) ||
                MapConst.WWW_TDT.equals(mapLayer.getLayerType().toLowerCase()))){
            return;
        }
        if(mapLayer.getReleaseType().equals(MapConst.MAP_SERVICE_TYPE_ARCGIS) || mapLayer.getReleaseType().equals(MapConst.MAP_SERVICE_TYPE_PLATFORM)
                || mapLayer.getReleaseType().equals(MapConst.MAP_SERVICE_TYPE_BASIS_PLATFORM)){
            if(mapLayerService.ogcFlag(mapLayer.getLayerUrl())){
                return;
            }
            Map<String, String> params = new HashMap();
            params.put("f", "pjson");
            if (mapLayer.getReleaseType().equals(MapConst.MAP_SERVICE_TYPE_PLATFORM) || mapLayer.getReleaseType().equals(MapConst.MAP_SERVICE_TYPE_BASIS_PLATFORM)) {
                JSONObject authKeyJson = JSONObject.fromObject(mapLayer.getAuthKey());
                params.put(authKeyJson.getString("key"), authKeyJson.getString("value"));
            }
            String serviceResult = ReadFileUtil.getStringByUrl(mapLayer.getLayerUrl(), params);
            JSONArray layerFieldArray=null;
            if(StringUtils.isNotBlank(serviceResult)){
                JSONObject jsonObject = JSONObject.fromObject(serviceResult);
                Object fields = jsonObject.get("fields");
                if(fields!=null&&!"null".equalsIgnoreCase(fields.toString())){
                    layerFieldArray= (JSONArray) fields;
                }
            }
            // 获取图层URL
            // String layerUrl = mapLayer.getLayerUrl() + "/" + mapLayer.getLayerTable() + "?f=pjson";
            if(layerFieldArray==null||layerFieldArray.isEmpty()){
                String layerUrl = mapLayer.getLayerUrl() + "/" + mapLayer.getLayerTable();
                // 根据图层URL获取json数据集
                String layerJsonStr = ReadFileUtil.getStringByUrl(layerUrl, params);
                JSONObject layerJson = JSONObject.fromObject(layerJsonStr);
                Object fields = layerJson.get("fields");
                if(fields!=null&&!"null".equalsIgnoreCase(fields.toString())){
                    layerFieldArray= (JSONArray) fields;
                }else{
                    Object layers = layerJson.get("layers");
                    if(layers!=null){
                        JSONArray layerList = (JSONArray) layers;
                        for (int i=0;i<layerList.size();i++){
                            JSONObject oneLayer = (JSONObject) layerList.get(i);
                            if(oneLayer.get("id").toString().equals(mapLayer.getLayerTable())){
                                Object fieldsStr = oneLayer.get("fields");
                                if(fieldsStr!=null&&!"null".equalsIgnoreCase(fieldsStr.toString())){
                                    layerFieldArray = (JSONArray) fieldsStr;
                                }
                                break;
                            }
                        }
                    }
                }
            }
            // 获取图层几何类型
            List<MapLayerField> layerFields = mapLayerFieldService.getLayerFieldByParseResult(layerFieldArray, layerId, null);
            mapLayerFieldService.saveMapLayerField(layerFields);
        }
    }

    @Override
    public List<MapLayer> getBaseMap() {
        return mapLayerMapper.getBaseMap();
    }

    @Override
    public List<MapLayer> lazyLoadDivisionMapLayer(String parentId,boolean filter) {
        return mapLayerMapper.lazyLoadDivisionMapLayer(parentId,filter);
    }

    @Override
    public List<MapLayer> lazyLoadMapLayer(String dirId, String parentId) {
        return mapLayerMapper.lazyLoadMapLayer(dirId,parentId);
    }

    @Override
    public void deleteById(String... ids) {
        for (String id : ids) {
            // 删除关联元数据
            mapMetadataService.deleteByLayerId(id);
            //删除关联字段信息
            mapLayerFieldService.deleteByLayerId(id);
            // 删除图层
            mapLayerMapper.deleteById(id);
        }
    }

    @Override
    public List<MapLayer> listByOrg(List<String> orgIds) {
        return mapLayerMapper.listByOrg(orgIds);
    }

    @Override
    public List<MapLayer> listByParentId(String parentId) {
        return mapLayerMapper.listByParentId(parentId);
    }

    @Override
    public List<MapLayer> getServiceAndLayer(List<MapLayer> dataList){
        List<MapLayer> result = new ArrayList<>();
        if(dataList==null||dataList.isEmpty()){
            return result;
        }
        for (MapLayer mapLayer : dataList){
            String name = mapLayer.getName();
            int index =-1;
            if(StringUtils.isNotBlank(name)){
                index = mapLayer.getName().indexOf(MapConst.TILE_INFO_STR);
            }
            // 展示的图层
            if("3".equals(mapLayer.getType())&&(index<0)){
                result.add(mapLayer);
            }
            // 目录或者服务
            if("1".equals(mapLayer.getType())||"2".equals(mapLayer.getType())){
                result.add(mapLayer);
            }
        }
        return result;
    }

    /**
     * MapImageLayer
     * tclx_rest
     *
     * TileLayer
     * tclx_tile
     *
     * ImageryLayer
     * tclx_imagery
     *
     * ImageryTileLayer
     * tclx_imagerytile
     *
     * FeatureLayer
     * tclx_feature
     *
     * VectorTileLayer
     * tclx_vectortile
     *
     * IntegratedMeshLayer
     * tclx_mesh
     *
     * SceneLayer
     * tclx_scene
     *
     * BuildingSceneLayer
     * tclx_bim
     *
     * ElevationLayer
     * tclx_elevation
     *
     * WMS
     * tclx_wms
     *
     * WFS
     * tclx_wfs
     *
     * WMTS
     * tclx_wmts
     * 返回图层类型
     * @return
     */
    @Override
    public String getLayerType(String serverUrl, com.alibaba.fastjson.JSONObject serverResult){
        List<String> ogc = new ArrayList<>();
        String[] urlArray = serverUrl.split("/");
        String serverType = urlArray[urlArray.length - 1].split("\\?")[0];
        if(MapConst.WFS.equals(serverType)){
            return MapConst.WFS_STR;
        }
        if(MapConst.WMS.equals(serverType)){
            return MapConst.WMS_STR;
        }
        if(MapConst.WMTS.equals(serverType)){
            return MapConst.WMTS_STR;
        }
        String layerType="";
        if(serverUrl.indexOf(MapConst.MAP_SERVER_STR)>0){
            Object tileInfo = serverResult.get("tileInfo");
            if(tileInfo==null){
                layerType= MapConst.MAP_IMAGE_LAYER;
            }else{
                layerType= MapConst.TILE_LAYER;
            }
        }
        if(serverUrl.indexOf(MapConst.IMAGE_SERVER_STR)>0){
            Object cacheType = serverResult.get("cacheType");
            if(cacheType==null){
                layerType= MapConst.IMAGERY_LAYER;
            }else if("Map".equals(cacheType.toString())){
                layerType= MapConst.IMAGERY_TILE_LAYER;
            }else if("Elevation".equals(cacheType.toString())){
                layerType= MapConst.ELEVATION_LAYER;
            }
        }
        if(serverUrl.indexOf(MapConst.SCENE_LAYER_STR)>0){
            Object layerTypeObj = serverResult.get("layerType");
            if(layerTypeObj==null){
                com.alibaba.fastjson.JSONArray layers = (com.alibaba.fastjson.JSONArray) serverResult.get("layers");
                com.alibaba.fastjson.JSONObject layer = (com.alibaba.fastjson.JSONObject)layers.get(0);
                layerTypeObj = layer.get("layerType");
            }
            if(layerTypeObj!=null){
                String layerObjStr = layerTypeObj.toString();
                if("3DObject".equals(layerObjStr)||"Point".equals(layerObjStr)){
                    layerType= MapConst.SCENE_LAYER;
                }else if("Building".equals(layerObjStr)){
                    layerType= MapConst.BUILDING_SCENE_LAYER;
                }else if("IntegratedMesh".equals(layerObjStr)){
                    layerType= MapConst.INTEGRATED_MESH_LAYER;
                }
            }
        }
        if(serverUrl.indexOf(MapConst.FEATURE_SERVER_STR)>0){
            layerType= MapConst.FEATURE_LAYER;
        }
        if(serverUrl.indexOf(MapConst.VECTOR_TILE_SERVER_STR)>0){
            layerType= MapConst.VECTOR_TILE_LAYER;
        }
        return layerType;
    }

    @Override
    public boolean ogcFlag(String layerUrl) {
        String[] urlArray = layerUrl.split("/");
        String serverType = urlArray[urlArray.length - 1].split("\\?")[0];
        List<String> ogc = new ArrayList<>();
        ogc.add(MapConst.WFS);
        ogc.add(MapConst.WMS);
        ogc.add(MapConst.WMTS);
        return ogc.contains(serverType);
    }

    @Override
    public boolean deleteChildAndField(List<String> ids) {
        if(ids==null||ids.isEmpty()){
            return false;
        }
        LambdaQueryWrapper<MapLayer> wrapper = Wrappers.lambdaQuery();
        wrapper.in(MapLayer::getParentId,ids);
        List<MapLayer> list = list(wrapper);
        if(list==null||list.isEmpty()){
            return false;
        }
        List<String> collect = list.stream().map(MapLayer::getId).collect(Collectors.toList());
        for (String layerId : collect) {
            deleteById(layerId);
        }
        return true;
    }

    @Override
    public boolean syncLayerName(List<MapLayer>layers) {
        if(layers==null||layers.isEmpty()){
            return false;
        }
        projectDirMapper.syncLayerNameByLayerId(layers);
        functionDirMapper.syncLayerNameByLayerId(layers);
        return true;
    }

    @Override
    public Integer getMaxSortByParentId(String parentId) {
        return mapLayerMapper.getMaxSortByParentId(parentId);
    }


}
